package com.hp.common.exception;

import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.hp.common.base.CodedEnum;
import com.hp.common.base.CommonError;
import com.hp.common.base.CommonResult;
import com.hp.common.base.constant.GlobalErrEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 全局异常处理类
 */
@ControllerAdvice
public class DefaultExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);

    /**
     * 服务层异常
     * @param e
     * @return
     */
    @ExceptionHandler(BizException.class)
    @ResponseBody
    public CommonResult<?> serviceExceptionHandler(BizException e){
        log.error("服务层异常：",e);
        return CommonResult.error(e.getError());
    }

    public CommonResult<?> invalidDefinitionExceptionHandler(HttpMessageConversionException e){
        log.error("json转换异常:",e);
        if(e.getCause().getClass().isAssignableFrom(InvalidDefinitionException.class)){
            final InvalidDefinitionException invalidDefinitionException = (InvalidDefinitionException) e.getCause();
            try{
                String typeName = invalidDefinitionException.getType().getTypeName();
                typeName = typeName.substring(20,typeName.length()-1);
                Class<?> clazz = Class.forName(typeName);
                List<Map<String,Object>> list = new ArrayList<>();
                Arrays.stream(clazz.getEnumConstants()).forEach(i ->{
                    if(i instanceof CodedEnum){
                        CodedEnum coded = (CodedEnum) i;
                        int value = coded.getValue();
                        String name = coded.getName();
                        Map<String,Object> map = new HashMap<>();
                        map.put("value",value);
                        map.put("name",name);
                        list.add(map);
                    }
                });
                return CommonResult.error(new CommonError() {
                    @Override
                    public int getValue() {
                        return GlobalErrEnum.GL99990100.getValue();
                    }

                    @Override
                    public String getName() {
                        return invalidDefinitionException.getMessage();
                    }
                },list);
            }catch (ClassNotFoundException e1){
                return CommonResult.fail(e1);
            }
        }else if(e.getCause().getClass().isAssignableFrom(InvalidFormatException.class)){
            final  InvalidFormatException invalidFormatException = (InvalidFormatException) e.getCause();

            return CommonResult.error(new CommonError() {
                @Override
                public int getValue() {
                    return GlobalErrEnum.GL99990100.getValue();
                }

                @Override
                public String getName() {
                    return invalidFormatException.getMessage();
                }
            },null);
        }
        return CommonResult.fail();
    }

    /**
     * 控制层参数校验异常
     * @param e
     * @return
     */
    public CommonResult<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e){
        log.error("参数校验异常：{}",e.getMessage());
        final String errorMsg = String.join(",",e.getBindingResult().getAllErrors().stream().map(item ->{
            return item.getDefaultMessage();
        }).collect(Collectors.toList()));
        return CommonResult.error(new CommonError() {
            @Override
            public int getValue() {
                return GlobalErrEnum.GL99990100.getValue();
            }

            @Override
            public String getName() {
                return errorMsg;
            }
        });
    }

    /**
     * 其他异常
     * @param e
     * @return
     */
    public CommonResult<?> excetionHandler(Exception e){
        log.error("未捕获异常:",e);
        return CommonResult.fail(e.getMessage(),null);
    }
}
